<template>
  <div id="app">
    <!-- name属性不能随意添加 -->
    <router-view />
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { Action, Mutation, Getter, namespace } from "vuex-class";
import { Webim } from "@/utils/types";
import {
  DIALOGUE,
  ImClient,
  MsgTypeKV,
  REGISTER,
  MsgTypeVK
} from "@/api/socket/imClient";
import { Response } from "@/api/bean";
import MessageMixin from '@/mixins';
import querystring from 'querystring';
import { Api } from './api/http';
declare const $Vue: Vue;
declare const webim: Webim;
const chatModule = namespace("chatModule");
const userModule = namespace("userModule");

@Component<App>({
  mixins: [MessageMixin],
  sockets: {
    // 获取登录用户信息
    connect: function (res) {
      
      this.getReloadHref();
      let token: any = null;
      let str = window.location.href.split('?')[1];
      let qs = querystring.parse(str);
      if (qs.token) {
        token = qs.token;
        sessionStorage.setItem("token", token);
      } else {
        token = sessionStorage.getItem('token');
        if (!token) {
          // this.$createToast({
          //   txt: "无效的token",
          //   type: "warn",
          //   time: 3000
          // }).show();
          // window.location.reload();
          this.getReloadHref();
          return;
        }
      }
      this.$socket.emit(REGISTER, {
        token,
      });
      // console.warn("connect", res);
    },
    register: function (res) {
      console.warn(REGISTER, res);
      if (res.result !== 0) {
        this.getReloadHref();
        // alert(res.message);
        return;
      }
      // 获取登录信息
      this.getLoginInfo();
    },
    /**
     * 监听的消息事件
     */
    dialogue: function (res) {
      if (typeof res === "string") {
        res = JSON.parse(res);
      }
      if (typeof res === "object") {
        this.onMessage(res);
      } else {
        console.warn("没用的消息：" + res);
      }
    },
    error: function (res) {
      console.log("error", res);
    },
    disconnect: function (res) {
      console.log("disconnect", res);
    },
    closelink: function (res) {
      console.log("closelink", res);
    },
    reconnect_attempt: function (res) {
      console.log("closelink", res);
    },
    reconnecting: function (res) {
      console.log("reconnecting", res);
    },
    reconnect_error: function (res) {
      console.log("reconnect_error", res);
      window.location.reload();
    },
    reconnect_failed: function (res) {
      console.log("reconnect_failed", res);
    }
  }
})
export default class App extends Vue {
  // 进行系统登录

  @userModule.Action("saveLoginInfoFN") saveLoginInfoFN: any;
  @userModule.State("loginInfo") loginInfo: any;

  @chatModule.Action("saveWxShareDataFN") saveWxShareDataFN: any;


  private onGroupSystemNotifys: any = {
    "1": this.onApplyJoinGroupRequestNotify, //申请加群请求（只有管理员会收到）
    "2": this.onApplyJoinGroupAcceptNotify, //申请加群被同意（只有申请人能够收到）
    "3": this.onApplyJoinGroupRefuseNotify, //申请加群被拒绝（只有申请人能够收到）
    "4": this.onKickedGroupNotify, //被管理员踢出群（只有被踢者接收到）
    "5": this.onDestoryGroupNotify, //群被解散（全员接收）
    "6": this.onCreateGroupNotify, //创建群（创建者接收）
    "7": this.onInvitedJoinGroupNotify, //邀请加群（被邀请者接收）
    "8": this.onQuitGroupNotify, //主动退群（主动退出者接收）
    "9": this.onSetedGroupAdminNotify, //设置管理员（被设置者接收）
    "10": this.onCanceledGroupAdminNotify, //取消管理员（被取消者接收）
    "11": this.onRevokeGroupNotify, //群已被回收（全员接收）
    "255": this.onCustomGroupNotify, //用户自定义通知（默认全员接收）
    "12": this.onInvitedJoinGroupNotifyRequest, //邀请加群(被邀请者接收,接收者需要同意)
    "15": this.onReadedSyncGroupNotify, //群消息已读同步通知

  };


  /**
   * 监听 C2C 系统消息通道
   */
  private onC2cEventNotifys: any = {
    "92": this.onMsgReadedNotify, //消息已读通知,
    "96": this.onMultipleDeviceKickedOut
  };

  private listners: any = {
    onConnNotify: this.onConnNotify, //监听连接状态回调变化事件，选填
    jsonpCallback: this.jsonpCallback, //IE9（含）以下浏览器用到的 jsonp 回调函数
    onMsgNotify: this.onMsgNotify, //监听新消息（私聊，普通群（非直播聊天室）消息，全员推送消息）事件，必填
    onBigGroupMsgNotify: this.onBigGroupMsgNotify, //监听新消息（直播聊天室）事件，直播场景下必填
    onGroupSystemNotifys: this.onGroupSystemNotifys, //监听（多终端同步）群系统消息事件，如果不需要监听，可不填
    onGroupInfoChangeNotify: this.onGroupInfoChangeNotify, //监听群资料变化事件，选填
    onFriendSystemNotifys: this.onFriendSystemNotifys, //监听好友系统通知事件，选填
    onProfileSystemNotifys: this.onProfileSystemNotifys, //监听资料系统（自己或好友）通知事件，选填
    onKickedEventCall: this.onKickedEventCall, //被其他登录实例踢下线
    onC2cEventNotifys: this.onC2cEventNotifys, //监听 C2C 系统消息通道
    onLongPullingNotify(data: any) {
      console.debug('长轮询事件通知', data)
    }
  };

  // 微信签名数据
  private wxConfigData: any = {};
  // 重试签名次数
  private wxRetryTimes: number = 0;

  protected mounted() {
    // 从服务端取得相关信息用于登录
    window.onbeforeunload = () => {
      if (this.$socket) {
        this.$socket.close();
      }
      if (this.loginInfo.identifier) {
        webim.logout((resp: any) => {
        }, (err: any) => { })
      }
    }
  }

  /**
   * 配置微信SDK
   */
  private configWX(data: any) {
    wx.config({
      debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，参数信息会通过log打出，仅在pc端时才会打印。
      appId: data.shareAppId, // 必填，公众号的唯一标识
      timestamp: data.shareTimestamp, // 必填，生成签名的时间戳
      nonceStr: data.shareNonceStr, // 必填，生成签名的随机串
      signature: data.shareSignature, // 必填，签名
      jsApiList: ["startRecord", "stopRecord", "playVoice", "pauseVoice", "stopVoice", "onVoiceRecordEnd", "uploadVoice", "updateAppMessageShareData", "updateTimelineShareData"] // 必填，需要使用的JS接口列表
    });
    wx.ready(() => {
      // config信息验证后会执行ready方法，所有接口调用都必须在config接口获得结果之后，config是一个客户端的异步操作，所以如果需要在页面加载时就调用相关接口，则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口，则可以直接调用，不需要放在ready函数中。
      this.wxShare(data);
    });

    wx.error((err) => {
      // config信息验证失败会执行error函数，如签名过期导致验证失败，具体错误信息可以打开config的debug模式查看，也可以在返回的res参数中查看，对于SPA可以在这里更新签名。
      console.error('微信签名失败', err.errMsg);
      if (this.wxRetryTimes <= 5) {
        this.configWX(this.wxConfigData);
        this.wxRetryTimes++;
      }
    });
  }

  /**
   * 微信签名
   */
  private wxShare(data: any) {

    // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
    wx.updateAppMessageShareData({
      title: '超级社群', // 分享标题
      desc: '', // 分享描述
      link: data.shareLink, // 分享链接，该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
      imgUrl: data.shareLink, // 分享图标
      success: function () {
        // 设置成功
      }
    });
    // 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
    wx.updateTimelineShareData({
      title: '超级社群', // 分享标题
      link: data.shareLink, // 分享链接，该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
      imgUrl: data.shareLink, // 分享图标
      success: function () {
        // 设置成功
      }
    })

  }

  /**
   * 从服务端获取登录信息
   */
  private getLoginInfo() {
    this.sendMessage(MsgTypeKV.login, {
      signUrl: window.location.href,
    });
  }

  /**
   * 服务端所有发送的消息从此处派发
   */
  private onMessage(res: any) {
    // console.error("onMessage", res);
    let type = res.type;
    let func = this[MsgTypeVK[type]];
    let event = "";

    if (typeof func === "function") {
      // 回调到对应的方法
      func(JSON.parse(res.text));
    }
    if (MsgTypeVK[type]) {
      event = MsgTypeVK[type]
      // 全局派发
      $Vue.$emit(event, JSON.parse(res.text));
    } else {
      // 需要遍历派发 code长度为5
      let data = JSON.parse(res.text);
      let code = res.type + "" + data.paramType;
      for (let key in MsgTypeVK) {
        if (code == key) {
          event = MsgTypeVK[key];
        }
      }
      $Vue.$emit(event, JSON.parse(res.text));
    }
    console.error('----服务端消息事件----', type, event, JSON.parse(res.text));
  }

  private $tokenExpired(data: any) {
    if (!window.location.host.match('5600')) {
      window.location.href = data.authAddr;
    }
  }

  /**
   * 完成登录相关操作 1001
   */
  private $login(data: any) {
    if (data.result === 0) {
      let $data = data.data;

      localStorage.setItem('userId', data.userId);
      localStorage.setItem('identifier', $data.identifier);

      const loginInfo = {
        identifier: $data.identifier,
        appIDAt3rd: $data.appIDAt3rd,
        sdkAppID: $data.sdkAppID,
        userSig: $data.userSig,
      };

      // const wxConfig = {
      //   appId: $data.shareAppId,
      //   timestamp: $data.shareAppId,
      //   nonceStr: $data.shareAppId,
      //   signature: $data.shareAppId,
      // };

      // this.configWX(wxConfig);

      const options = {
        debug: false,
      };

      this.saveLoginInfoFN(loginInfo);

      webim.login(
        loginInfo,
        this.listners,
        options,
        this.onLoginSuccessCb,
        this.onLoginFailCb,
      );
    }
  }


  /**
   * 获取微信签名
   */
  private $getWxConfig(data: any) {
    if (data.result === 0) {
      this.wxConfigData = data;
      this.configWX(data);

      this.saveWxShareDataFN(data);
    } else {

    }
  }

  private async getReloadHref() {
    const { data } = await Api.getReloadHref.r();
    console.warn('getReloadHref', data)
    if (data.result === 600) {
      let host = window.location.host
      if (!host.match('5600')) {
        window.location.href = data.data.autoAddr;
      }
    } else {

    }
  }

  /**
   * 登录成功
   */
  private onLoginSuccessCb(res: any) {
    console.warn("onLoginSuccessCb", res);
    this.saveLoginInfoFN({
      headurl: res.headurl,
      identifierNick: res.identifierNick
    });
    // 登录之后才从webim获取到相关信息
    $Vue.$emit('onWebimLogined');
  }

  /**
   * 登录失败
   */
  private onLoginFailCb(res: any) {
    // console.warn("onLoginFailCb", res);
    this.$createToast({
      txt: "IM系统登录失败, 尝试重新登录...",
      type: "warn",
      time: 3000
    }).show();
    window.location.reload();
    // webim.login(
    //   this.loginInfo,
    //   this.listners,
    //   {},
    //   this.onLoginSuccessCb,
    //   this.onLoginFailCb,
    // );
  }

  /**
   * 监听连接状态回调变化事件，选填
   */
  private onConnNotify(resp: any) {
    let info;
    switch (resp.ErrorCode) {
      case webim.CONNECTION_STATUS.ON:
        webim.Log.warn('建立连接成功: ' + resp.ErrorInfo);
        break;
      case webim.CONNECTION_STATUS.OFF:
        info = '连接已断开，无法收到新消息，请检查下你的网络是否正常: ' + resp.ErrorInfo;
        this.$createToast({
          txt: info,
          type: "warn",
          time: 5000
        }).show();
        webim.Log.warn(info);
        break;
      case webim.CONNECTION_STATUS.RECONNECT:
        info = '连接状态恢复正常: ' + resp.ErrorInfo;
        this.$createToast({
          txt: info,
          type: "correct",
          time: 3000
        }).show();
        webim.Log.warn(info);
        break;
      default:
        webim.Log.error('未知连接状态: =' + resp.ErrorInfo);
        break;
    }
  }
  /**
   * IE9（含）以下浏览器用到的 jsonp 回调函数
   */
  private jsonpCallback() { }
  /**
   * 监听新消息（私聊，普通群（非直播聊天室）消息，全员推送消息）事件，必填
   */
  private onMsgNotify(data: any) {
    $Vue.$emit("onMsgNotify", data);
  }
  /**
   * 监听新消息（直播聊天室）事件，直播场景下必填
   */
  private onBigGroupMsgNotify() { }

  /**
   * 监听群资料变化事件，选填
   */
  private onGroupInfoChangeNotify() { }

  /**
   * 监听好友系统通知事件，选填
   */
  private onFriendSystemNotifys() { }

  /**
   * 监听资料系统（自己或好友）通知事件，选填
   */
  private onProfileSystemNotifys() { }

  /**
   * 被其他登录实例踢下线
   */
  private onKickedEventCall(data: any) {
    $Vue.$emit("onKickedEventCall", data);
  }


  /************* 群事件消息 ************/

  /**
   * 申请加群请求（只有管理员会收到）
   */
  private onApplyJoinGroupRequestNotify(data: any) {
    $Vue.$emit("onApplyJoinGroupRequestNotify", data);
  }

  /**
   * 申请加群被同意（只有申请人能够收到）
   */
  private onApplyJoinGroupAcceptNotify(data: any) {
    $Vue.$emit("onApplyJoinGroupAcceptNotify", data);
  }

  /**
   * 申请加群被拒绝（只有申请人能够收到）
   */
  private onApplyJoinGroupRefuseNotify(data: any) {
    $Vue.$emit("onApplyJoinGroupRefuseNotify", data);
  }

  /**
   * 被管理员踢出群（只有被踢者接收到）
   */
  private onKickedGroupNotify(data: any) {
    $Vue.$emit("onKickedGroupNotify", data);
  }

  /**
   * 群被解散（全员接收）
   */
  private onDestoryGroupNotify(data: any) {
    $Vue.$emit("onDestoryGroupNotify", data);

  }

  /**
   * 创建群（创建者接收）
   */
  private onCreateGroupNotify(data: any) {
    $Vue.$emit("onCreateGroupNotify", data);

  }

  /**
   * 邀请加群（被邀请者接收）
   */
  private onInvitedJoinGroupNotify(data: any) {
    $Vue.$emit("onInvitedJoinGroupNotify", data);
  }

  /**
   * 主动退群（主动退出者接收）
   */
  private onQuitGroupNotify(data: any) {
    $Vue.$emit("onQuitGroupNotify", data);
  }

  /**
   * 设置管理员（被设置者接收）
   */
  private onSetedGroupAdminNotify(data: any) {
    $Vue.$emit("onSetedGroupAdminNotify", data);
  }

  /**
   * 取消管理员（被取消者接收）
   */
  private onCanceledGroupAdminNotify(data: any) {
    $Vue.$emit("onCanceledGroupAdminNotify", data);
  }

  /**
   * 群已被回收（全员接收）
   */
  private onRevokeGroupNotify(data: any) {
    $Vue.$emit("onRevokeGroupNotify", data);
  }

  /**
   * 用户自定义通知（默认全员接收）
   */
  private onCustomGroupNotify(data: any) {
    $Vue.$emit("onCustomGroupNotify", data);
  }

  /**
   * 邀请加群(被邀请者接收,接收者需要同意)
   */
  private onInvitedJoinGroupNotifyRequest(data: any) {
    $Vue.$emit("onInvitedJoinGroupNotifyRequest", data);
  }

  /**
   * 群消息已读同步通知
   */
  private onReadedSyncGroupNotify(data: any) {
    $Vue.$emit("onReadedSyncGroupNotify", data);
  }

  /**
   * 消息已读通知,
   */
  private onMsgReadedNotify(data: any) {
    $Vue.$emit("onMsgReadedNotify", data);
  }

  /**
   * 多终端登录被踢
   */
  private onMultipleDeviceKickedOut(data: any) {
    $Vue.$emit("onMultipleDeviceKickedOut", data);
  }
}
</script>


<style lang="stylus">
#app
  font-family 'Avenir', Helvetica, Arial, sans-serif
  -webkit-font-smoothing antialiased
  -moz-osx-font-smoothing grayscale
  text-align center
  color #2c3e50
  width 100%
  height 100%
#nav
  padding 30px
  a
    font-weight bold
    color #2c3e50
    &.router-link-exact-active
      color #42b983
</style>
